import { profile } from '@/utils/decorators';
import { guardObj, safeAccess } from '@/utils/functions/safeAccesss';
import { Logger } from '@/utils/logger';
import { RoomPlannerManager } from './roomplanner';


/**
 * 殖民地，有三种模式（正常模式 `NormalColony`，冲级模式 `GCLFarmColony`，
 * 经济模式 `EconomicColony`），分别由 `ColonyFactory` 实例化
 */
export abstract class Colony {

    // properties =================================================

    readonly name: string;
    readonly outpostNames: string[];
    capital: Room;
    outposts: Room[];
    creeps: Creep[];
    creepsByRole: Record<string, Creep[]>;
    roomPlanner: RoomPlannerManager;

    // methods ====================================================

    constructor(capitalRoom: string, outpostNames: string[] = []) {
        this.name = capitalRoom;
        this.outpostNames = outpostNames;
        this.outposts = [];
        this.creeps = [];
        this.creepsByRole = {};
    }

    build() {
        // 注册房间构成
        this.capital = Game.rooms[this.name];
        this.outposts = this.outpostNames.map(n => Game.rooms[n]).filter(r => !!r);
        // 注册爬
        this.creeps = Empire.getCreepsByColony(this.name);
        this.creepsByRole = this.creeps.groupBy(creep => safeAccess(creep, ['memory', 'role']));
        // 构建 memory
        this.__memory();
        // 自动规划
        this.roomPlanner = new RoomPlannerManager(this);
    }

    @profile
    refresh() {
        // 更新一切 non-live objects
        this.capital = Game.rooms[this.name];
        this.outposts = this.outpostNames.map(n => Game.rooms[n]).filter(r => !!r);
        this.creeps = Empire.getCreepsByColony(this.name);
        this.creepsByRole = this.creeps.groupBy(creep => safeAccess(creep, ['memory', 'role']));
        // 刷新建筑
        this.capital.updateCache();
        this.outposts.forEach(o => o.updateCache());
    }

    abstract execute(): void;

    @profile
    run() {
        // 升级了，特殊事件
        if (this.capital.getController().level !== this.memory.originalLevel) {
            this.onLevelChange();
            this.memory.originalLevel = this.capital.getController().level;
        }
        // 特殊操作
        this.execute();
    }

    addOutpost(name: string) {
        if (/(W|E)\d+(N|S)\d+/.test(name)) {
            if (!this.memory.outpostNames) {
                this.memory.outpostNames = [name];
            }
            else {
                this.memory.outpostNames.push(name);
            }
        }
        else {
            throw new Error(`无效的 outpost 名称：${name}`);
        }
    }

    getCreepsByRole(role: CreepRole) {
        return this.creepsByRole[role] || [];
    }

    // countCreepsByRole(role: CreepRole) {
    //     return this.getCreepsByRole(role).length + (this.memory.spawnList || []).length;
    // }

    // events ====================================================

    private onLevelChange() {
        const currentLevel = this.capital.getController().level;
        const delta = currentLevel - this.memory.originalLevel;
        if (delta > 0) {
            // 升级了，放置自动规划的建筑
            if (!this.memory.structurePlan || !this.memory.structurePlan[currentLevel]) {
                this.roomPlanner.replan();
            }
            Object.entries(this.memory.structurePlan[currentLevel]).forEach(_ => {
                const [_structureType, positions] = _;
                positions.forEach(pos => {
                    const [x, y] = pos.split('/');
                    const structureType = <BuildableStructureConstant>_structureType;
                    if (structureType === STRUCTURE_SPAWN) {
                        // 因为自动规划会把第一个 spawn 也规划掉，所以 rcl 不够时直接跳过
                        if (currentLevel >= 6) {
                            Memory.spawnCounter ??= 1;
                            const name = `Spawn${++Memory.spawnCounter}`;
                            this.capital.createConstructionSite(~~x, ~~y, STRUCTURE_SPAWN, name)
                        }
                    }
                    else {
                        this.capital.createConstructionSite(~~x, ~~y, structureType);
                    }
                });
            });

        }
        else {
            // 降级了，警告
            Logger.warn(`殖民地 "${this.name}" 的主控制器降级了！请尽快检查问题！`, 'colony', true);
        }
    }

    // getters and setters ========================================

    private __memory() {
        return guardObj(Memory.colony, this.name, {
            originalLevel: 1
        });
    }
    get memory() {
        return this.__memory();
    }
    set memory(obj: ColonyMemory) {
        Memory.colony[this.name] = obj;
    }

    get operatingMode() {
        return this.memory.operatingMode || 'normal';
    }
    set operatingMode(mode: ColonyOperatingMode) {
        this.memory.operatingMode = mode;
    }

    get level() {
        return this.capital.getController().level;
    }

}